diff options
author | Luca Barbato <lu_zero@gentoo.org> | 2006-03-21 22:53:10 +0000 |
---|---|---|
committer | Luca Barbato <lu_zero@gentoo.org> | 2006-03-21 22:53:10 +0000 |
commit | b3f6b4b9b2141b6406b171131ece28d2d79234c8 (patch) | |
tree | 38a15b1d1cdbce775ce89c745c67a29ee42ef5e5 /x11-drivers | |
parent | net-analyzer/iptraf:suid - Allow app to be run with suid root (diff) | |
download | historical-b3f6b4b9b2141b6406b171131ece28d2d79234c8.tar.gz historical-b3f6b4b9b2141b6406b171131ece28d2d79234c8.tar.bz2 historical-b3f6b4b9b2141b6406b171131ece28d2d79234c8.zip |
Fixed hangup on new Apple PowerBook
Package-Manager: portage-2.1_pre5-r4
Diffstat (limited to 'x11-drivers')
-rw-r--r-- | x11-drivers/xf86-video-ati/ChangeLog | 8 | ||||
-rw-r--r-- | x11-drivers/xf86-video-ati/Manifest | 25 | ||||
-rw-r--r-- | x11-drivers/xf86-video-ati/files/xf86-video-ati-6.5.7.3-hangup-ppc.patch | 359 | ||||
-rw-r--r-- | x11-drivers/xf86-video-ati/xf86-video-ati-6.5.7.3.ebuild | 3 |
4 files changed, 377 insertions, 18 deletions
diff --git a/x11-drivers/xf86-video-ati/ChangeLog b/x11-drivers/xf86-video-ati/ChangeLog index 2c1a422aa521..b0935c3141da 100644 --- a/x11-drivers/xf86-video-ati/ChangeLog +++ b/x11-drivers/xf86-video-ati/ChangeLog @@ -1,6 +1,12 @@ # ChangeLog for x11-drivers/xf86-video-ati # Copyright 1999-2006 Gentoo Foundation; Distributed under the GPL v2 -# $Header: /var/cvsroot/gentoo-x86/x11-drivers/xf86-video-ati/ChangeLog,v 1.21 2006/02/23 21:52:23 stefaan Exp $ +# $Header: /var/cvsroot/gentoo-x86/x11-drivers/xf86-video-ati/ChangeLog,v 1.22 2006/03/21 22:53:10 lu_zero Exp $ + + 21 Mar 2006; Luca Barbato <lu_zero@gentoo.org> + +files/xf86-video-ati-6.5.7.3-hangup-ppc.patch, + xf86-video-ati-6.5.7.3.ebuild: + Fixed hangup on new Apple PowerBook (rev 5,6 and 5,8), thanks to the people + in #mklinux for pointing it (and the ubuntu's mantainer) 23 Feb 2006; Stefaan De Roeck <stefaan@gentoo.org> xf86-video-ati-6.5.7.3.ebuild: diff --git a/x11-drivers/xf86-video-ati/Manifest b/x11-drivers/xf86-video-ati/Manifest index 7c60d7dc483c..c442f39874ae 100644 --- a/x11-drivers/xf86-video-ati/Manifest +++ b/x11-drivers/xf86-video-ati/Manifest @@ -1,22 +1,15 @@ ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -MD5 de5b94340049e50b776235633175b508 ChangeLog 3390 -RMD160 4cd2ce1d5a145af949e6685f7747e557f3bfc4ab ChangeLog 3390 -SHA256 19e3526dccbdb258146e7e505528e7da5429d3591334fedd629255dbecc5f1bd ChangeLog 3390 +MD5 30e763ce60f3d58ab13bbd8dd5dc33b8 ChangeLog 3660 +RMD160 2ff74a670bbf846b0f88d717d8827c794be314c7 ChangeLog 3660 +SHA256 ec35bd2b4f10a3f8ceef54ea2e820f97da06f21da08fb65ef62231beff4301ca ChangeLog 3660 MD5 d1f369a44c9f9eb25ac6ae8f05bf11c4 files/digest-xf86-video-ati-6.5.7.3 331 RMD160 37aa297f0980fecaa86112551924875d395613b3 files/digest-xf86-video-ati-6.5.7.3 331 SHA256 cbdb12ea8adca7bb493054a1b67c28192f8ac076f5d1cefe0acfbddd7e5d54dc files/digest-xf86-video-ati-6.5.7.3 331 +MD5 f2eaf0713b34e9ca2bd0abdce756d50e files/xf86-video-ati-6.5.7.3-hangup-ppc.patch 12572 +RMD160 1a87228c3b9be623b7af32c394fce68b4636f28b files/xf86-video-ati-6.5.7.3-hangup-ppc.patch 12572 +SHA256 780b2551ded8b2ea780bc83dcff9b8bd9330f7417bf1c4b98fefe1d5839e68e0 files/xf86-video-ati-6.5.7.3-hangup-ppc.patch 12572 MD5 a37bab73e2f24b213932c30997d3d360 metadata.xml 156 RMD160 c1274bdccf57603d580de0075ba07a35b7509560 metadata.xml 156 SHA256 5101ab0d4cc8c7125eea733c44e86962769bd77acaf53b69223b9cadcdd29055 metadata.xml 156 -MD5 e81d0b3fdbafb636a6e7f18878393867 xf86-video-ati-6.5.7.3.ebuild 872 -RMD160 170a7894cd447dca686a002965de9b128a9b8e20 xf86-video-ati-6.5.7.3.ebuild 872 -SHA256 705835f42861a275fea97119fd823d487cc21147f04787c719c845f5681d6434 xf86-video-ati-6.5.7.3.ebuild 872 ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.2.1 (GNU/Linux) - -iD8DBQFEB6bE2+ySkm8kpY0RAqhjAJ9ubnrQ3fQq1AMJk4hwSEtlFtUddgCeJ0cm -x6AaIF9Y4eVXh7kixyzut5E= -=p4eJ ------END PGP SIGNATURE----- +MD5 9757056c3b6f9b6b360e13b911ea9e3e xf86-video-ati-6.5.7.3.ebuild 917 +RMD160 62dfa567340fa6e74199ea04a5f91dac6deb0ffb xf86-video-ati-6.5.7.3.ebuild 917 +SHA256 f84ce1ef0729f02f4d1a4efc2e46744b6e1937279499cd8849c2ddfb4df9a1b2 xf86-video-ati-6.5.7.3.ebuild 917 diff --git a/x11-drivers/xf86-video-ati/files/xf86-video-ati-6.5.7.3-hangup-ppc.patch b/x11-drivers/xf86-video-ati/files/xf86-video-ati-6.5.7.3-hangup-ppc.patch new file mode 100644 index 000000000000..85e32737872a --- /dev/null +++ b/x11-drivers/xf86-video-ati/files/xf86-video-ati-6.5.7.3-hangup-ppc.patch @@ -0,0 +1,359 @@ +--- xserver-xorg-driver-ati-6.5.7.3.orig/src/radeon.h ++++ xserver-xorg-driver-ati-6.5.7.3/src/radeon.h +@@ -147,10 +147,16 @@ + CARD32 cap0_trig_cntl; + CARD32 cap1_trig_cntl; + CARD32 bus_cntl; +- CARD32 surface_cntl; + CARD32 bios_4_scratch; + CARD32 bios_5_scratch; + CARD32 bios_6_scratch; ++ CARD32 surface_cntl; ++ CARD32 surfaces[8][3]; ++ CARD32 mc_agp_location; ++ CARD32 mc_fb_location; ++ CARD32 display_base_addr; ++ CARD32 display2_base_addr; ++ CARD32 ov0_base_addr; + + /* Other registers to save for VT switches */ + CARD32 dp_datatype; +@@ -158,8 +164,6 @@ + CARD32 clock_cntl_index; + CARD32 amcgpio_en_reg; + CARD32 amcgpio_mask; +- +- CARD32 surfaces[8][3]; + + /* CRTC registers */ + CARD32 crtc_gen_cntl; +--- xserver-xorg-driver-ati-6.5.7.3.orig/src/radeon_driver.c ++++ xserver-xorg-driver-ati-6.5.7.3/src/radeon_driver.c +@@ -129,6 +129,7 @@ + static int RADEONValidateMergeModes(ScrnInfoPtr pScrn); + static void RADEONSetDynamicClock(ScrnInfoPtr pScrn, int mode); + static void RADEONUpdatePanelSize(ScrnInfoPtr pScrn); ++static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save); + + /* psuedo xinerama support */ + +@@ -2253,81 +2254,56 @@ + } + + /* Set up MC_FB_LOCATION and related registers */ +-static void +-RADEONSetFBLocation(ScrnInfoPtr pScrn) ++static void RADEONInitMemMapRegisters(ScrnInfoPtr pScrn,RADEONSavePtr save, ++ RADEONInfoPtr info) + { +- RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned char *RADEONMMIO = info->MMIO; +- CARD32 mc_fb_location; +- CARD32 mc_agp_location = INREG(RADEON_MC_AGP_LOCATION); +- CARD32 bus_cntl = INREG(RADEON_BUS_CNTL); +- +- OUTREG (RADEON_BUS_CNTL, bus_cntl | RADEON_BUS_MASTER_DIS); +- RADEONWaitForIdleMMIO(pScrn); + +- /* This function has many problems with newer cards. +- * Even with older cards, all registers changed here are not +- * restored properly when X quits, this will also cause +- * various problems, especially with radeonfb. +- * Since we don't have DRI support for R300 and above cards, +- * we just hardcode these values for now. +- * Need to revisit this whole function!!! +- */ ++ /* Default to existing values */ ++ save->mc_fb_location = INREG(RADEON_MC_FB_LOCATION); ++ save->mc_agp_location = INREG(RADEON_MC_AGP_LOCATION); + ++ /* ++ * Warning: A lot of the stuff down there is fairly bogus. For example, ++ * we use CONFIG_APER_SIZE which is only _half_ of the PCI exposed area ++ * since we might expose our VRAM in 2 different non overlapping apertures ++ * depending on how the card is bootstrapped. ++ * ++ * This will have to be fixed some day ... ++ */ + if (info->IsIGP) { +- mc_fb_location = INREG(RADEON_NB_TOM); ++ save->mc_fb_location = INREG(RADEON_NB_TOM); + ++ /* Hack ... FIXME or at least move elsewhere*/ + OUTREG(RADEON_GRPH2_BUFFER_CNTL, + INREG(RADEON_GRPH2_BUFFER_CNTL) & ~0x7f0000); + + } else + #ifdef XF86DRI + if ( info->directRenderingEnabled && info->drmMinor < 10 ) { +- mc_fb_location = (INREG(RADEON_CONFIG_APER_SIZE) - 1) & 0xffff0000U; ++ save->mc_fb_location = (INREG(RADEON_CONFIG_APER_SIZE) - 1) & 0xffff0000U; + } else + #endif + { + CARD32 aper0_base = INREG(RADEON_CONFIG_APER_0_BASE); + +- mc_fb_location = (aper0_base >> 16) +- | ((aper0_base + (INREG(RADEON_CONFIG_APER_SIZE) - 1) +- ) & 0xffff0000U); ++ save->mc_fb_location = (aper0_base >> 16) ++ | ((aper0_base + (INREG(RADEON_CONFIG_APER_SIZE) - 1) ++ ) & 0xffff0000U); + } + +- info->fbLocation = (mc_fb_location & 0xffff) << 16; ++ info->fbLocation = (save->mc_fb_location & 0xffff) << 16; + +- if (((mc_agp_location & 0xffff) << 16) != +- ((mc_fb_location & 0xffff0000U) + 0x10000)) { +- mc_agp_location = mc_fb_location & 0xffff0000U; +- mc_agp_location |= (mc_agp_location + 0x10000) >> 16; ++ if (((save->mc_agp_location & 0xffff) << 16) != ++ ((save->mc_fb_location & 0xffff0000U) + 0x10000)) { ++ save->mc_agp_location = save->mc_fb_location & 0xffff0000U; ++ save->mc_agp_location |= (save->mc_agp_location + 0x10000) >> 16; + } + +- RADEONWaitForIdleMMIO(pScrn); +- +- OUTREG(RADEON_MC_FB_LOCATION, mc_fb_location); +- OUTREG(RADEON_MC_AGP_LOCATION, mc_agp_location); +- OUTREG(RADEON_DISPLAY_BASE_ADDR, info->fbLocation); +- if (info->HasCRTC2) +- OUTREG(RADEON_DISPLAY2_BASE_ADDR, info->fbLocation); +- OUTREG(RADEON_OV0_BASE_ADDR, info->fbLocation); +- +- OUTREG (RADEON_BUS_CNTL, bus_cntl); +- RADEONWaitForIdleMMIO(pScrn); +- +- /* Set display0/1 priority up on r3/4xx in the memory controller for +- * high res modes if the user specifies HIGH for displaypriority +- * option. +- */ +- if ((info->DispPriority == 2) && IS_R300_VARIANT) { +- CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); +- if (info->MergedFB || pRADEONEnt->HasSecondary) { +- mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ +- } else { +- mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ +- } +- OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); +- } ++ save->display_base_addr = info->fbLocation; ++ save->display2_base_addr = info->fbLocation; ++ save->ov0_base_addr = info->fbLocation; + + } + +@@ -5518,6 +5494,8 @@ + unsigned char *RADEONMMIO = info->MMIO; + + if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) return FALSE; ++ RADEONSaveMemMapRegisters(pScrn, &info->ModeReg); ++ info->fbLocation = (info->ModeReg.mc_fb_location & 0xffff) << 16; + info->ModeReg.surface_cntl = INREG(RADEON_SURFACE_CNTL); + } else { + if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; +@@ -5605,8 +5583,6 @@ + hasDRI = info->directRenderingEnabled; + #endif + +- RADEONSetFBLocation(pScrn); +- + if (!fbScreenInit(pScreen, info->FB, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, +@@ -5837,7 +5813,66 @@ + return TRUE; + } + +-/* Write common registers (initialized to 0) */ ++/* Write memory mapping registers */ ++static void RADEONRestoreMemMapRegisters(ScrnInfoPtr pScrn, ++ RADEONSavePtr restore) ++{ ++ RADEONInfoPtr info = RADEONPTR(pScrn); ++ unsigned char *RADEONMMIO = info->MMIO; ++ int i; ++ ++ /* Write memory mapping registers only if their value change ++ * since we must ensure no access is done while they are ++ * reprogrammed ++ */ ++ if (INREG(RADEON_MC_FB_LOCATION) != restore->mc_fb_location || ++ INREG(RADEON_MC_AGP_LOCATION) != restore->mc_agp_location) { ++ CARD32 tmp; ++ ++ /* Make sure engine is idle. We assume the CCE is stopped ++ * at this point ++ */ ++ RADEONWaitForIdleMMIO(pScrn); ++ ++ /* Stop display & memory access */ ++ tmp = INREG(RADEON_CRTC_EXT_CNTL); ++ OUTREG(RADEON_CRTC_EXT_CNTL, tmp | RADEON_CRTC_DISPLAY_DIS); ++ tmp = INREG(RADEON_CRTC_GEN_CNTL); ++ tmp &= ~RADEON_CRTC_CUR_EN; ++ tmp |= RADEON_CRTC_DISP_REQ_EN_B; ++ OUTREG(RADEON_CRTC_GEN_CNTL, tmp); ++ if (info->HasCRTC2) { ++ tmp = INREG(RADEON_CRTC2_GEN_CNTL); ++ tmp &= ~RADEON_CRTC2_CUR_EN; ++ tmp |= RADEON_CRTC2_DISP_DIS | RADEON_CRTC2_DISP_REQ_EN_B; ++ OUTREG(RADEON_CRTC2_GEN_CNTL, tmp); ++ } ++ tmp = INREG(RADEON_OV0_SCALE_CNTL); ++ tmp &= ~RADEON_SCALER_ENABLE; ++ ++ /* Clear all surfaces */ ++ for (i = 0; i < 8; i++) { ++ OUTREG(RADEON_SURFACE0_INFO + 16 * i, 0); ++ OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * i, 0); ++ OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * i, 0); ++ } ++ ++ /* Make sure the chip settles down and set new map*/ ++ usleep(100000); ++ OUTREG(RADEON_MC_FB_LOCATION, restore->mc_fb_location); ++ OUTREG(RADEON_MC_AGP_LOCATION, restore->mc_agp_location); ++ /* Make sure map fully reached the chip */ ++ (void)INREG(RADEON_MC_FB_LOCATION); ++ ++ } ++ ++ /* Restore base addresses */ ++ OUTREG(RADEON_DISPLAY_BASE_ADDR, restore->display_base_addr); ++ OUTREG(RADEON_DISPLAY2_BASE_ADDR, restore->display2_base_addr); ++ OUTREG(RADEON_OV0_BASE_ADDR, restore->ov0_base_addr); ++} ++ ++/* Write common registers */ + static void RADEONRestoreCommonRegisters(ScrnInfoPtr pScrn, + RADEONSavePtr restore) + { +@@ -6457,6 +6492,7 @@ + + /* For Non-dual head card, we don't have private field in the Entity */ + if (!info->HasCRTC2) { ++ RADEONRestoreMemMapRegisters(pScrn, restore); + RADEONRestoreCommonRegisters(pScrn, restore); + RADEONRestoreCrtcRegisters(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); +@@ -6474,10 +6510,12 @@ + * order. Regardless the order of X server issuing the calls, we + * have to ensure we set registers in the right order!!! Otherwise + * we may get a blank screen. ++ * ++ * We always restore MemMap first, the saverec should be up to date ++ * in all cases + */ + if (info->IsSecondary) { +- if (!pRADEONEnt->RestorePrimary && !info->IsSwitching) +- RADEONRestoreCommonRegisters(pScrn, restore); ++ RADEONRestoreMemMapRegisters(pScrn, restore); + RADEONRestoreCrtc2Registers(pScrn, restore); + RADEONRestorePLL2Registers(pScrn, restore); + +@@ -6488,15 +6526,14 @@ + if (pRADEONEnt->RestorePrimary) { + pRADEONEnt->RestorePrimary = FALSE; + ++ RADEONRestoreCommonRegisters(pScrn, &restore0); + RADEONRestoreCrtcRegisters(pScrn, &restore0); + RADEONRestoreFPRegisters(pScrn, &restore0); + RADEONRestorePLLRegisters(pScrn, &restore0); + pRADEONEnt->IsSecondaryRestored = FALSE; + } + } else { +- if (!pRADEONEnt->IsSecondaryRestored) +- RADEONRestoreCommonRegisters(pScrn, restore); +- ++ RADEONRestoreMemMapRegisters(pScrn, restore); + if (info->MergedFB) { + RADEONRestoreCrtc2Registers(pScrn, restore); + RADEONRestorePLL2Registers(pScrn, restore); +@@ -6506,6 +6543,7 @@ + info->IsSwitching) { + pRADEONEnt->IsSecondaryRestored = FALSE; + ++ RADEONRestoreCommonRegisters(pScrn, restore); + RADEONRestoreCrtcRegisters(pScrn, restore); + RADEONRestoreFPRegisters(pScrn, restore); + RADEONRestorePLLRegisters(pScrn, restore); +@@ -6520,6 +6558,19 @@ + #endif + } + ++/* Read memory map */ ++static void RADEONSaveMemMapRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) ++{ ++ RADEONInfoPtr info = RADEONPTR(pScrn); ++ unsigned char *RADEONMMIO = info->MMIO; ++ ++ save->mc_fb_location = INREG(RADEON_MC_FB_LOCATION); ++ save->mc_agp_location = INREG(RADEON_MC_AGP_LOCATION); ++ save->display_base_addr = INREG(RADEON_DISPLAY_BASE_ADDR); ++ save->display2_base_addr = INREG(RADEON_DISPLAY2_BASE_ADDR); ++ save->ov0_base_addr = INREG(RADEON_OV0_BASE_ADDR); ++} ++ + /* Read common registers */ + static void RADEONSaveCommonRegisters(ScrnInfoPtr pScrn, RADEONSavePtr save) + { +@@ -6703,6 +6754,7 @@ + RADEONInfoPtr info = RADEONPTR(pScrn); + + RADEONTRACE(("RADEONSaveMode(%p)\n", save)); ++ RADEONSaveMemMapRegisters(pScrn, save); + RADEONSaveCommonRegisters(pScrn, save); + if (info->IsSecondary) { + RADEONSaveCrtc2Registers(pScrn, save); +@@ -6731,6 +6783,7 @@ + + RADEONTRACE(("RADEONSave\n")); + if (info->FBDev) { ++ RADEONSaveMemMapRegisters(pScrn, save); + fbdevHWSave(pScrn); + return; + } +@@ -6914,6 +6967,22 @@ + int stop_req, max_stop_req; + float read_return_rate, time_disp1_drop_priority; + ++ /* ++ * Set display0/1 priority up on r3/4xx in the memory controller for ++ * high res modes if the user specifies HIGH for displaypriority ++ * option. ++ */ ++ if ((info->DispPriority == 2) && IS_R300_VARIANT) { ++ CARD32 mc_init_misc_lat_timer = INREG(R300_MC_INIT_MISC_LAT_TIMER); ++ if (info->MergedFB || pRADEONEnt->HasSecondary) { ++ mc_init_misc_lat_timer |= 0x1100; /* display 0 and 1 */ ++ } else { ++ mc_init_misc_lat_timer |= 0x0100; /* display 0 only */ ++ } ++ OUTREG(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); ++ } ++ ++ + /* R420 family not supported yet */ + if (info->ChipFamily == CHIP_FAMILY_R420) return; + +@@ -8016,6 +8085,7 @@ + + info->Flags = mode->Flags; + ++ RADEONInitMemMapRegisters(pScrn, save, info); + RADEONInitCommonRegisters(save, info); + if (info->IsSecondary) { + if (!RADEONInitCrtc2Registers(pScrn, save, mode, info)) +@@ -8396,7 +8466,6 @@ + } else + if (!RADEONModeInit(pScrn, pScrn->currentMode)) return FALSE; + +- RADEONSetFBLocation(pScrn); + if (!info->IsSecondary) + RADEONRestoreSurfaces(pScrn, &info->ModeReg); + #ifdef XF86DRI + diff --git a/x11-drivers/xf86-video-ati/xf86-video-ati-6.5.7.3.ebuild b/x11-drivers/xf86-video-ati/xf86-video-ati-6.5.7.3.ebuild index 86555e017349..1d7b33488e2c 100644 --- a/x11-drivers/xf86-video-ati/xf86-video-ati-6.5.7.3.ebuild +++ b/x11-drivers/xf86-video-ati/xf86-video-ati-6.5.7.3.ebuild @@ -1,6 +1,6 @@ # Copyright 1999-2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/x11-drivers/xf86-video-ati/xf86-video-ati-6.5.7.3.ebuild,v 1.6 2006/03/03 02:14:40 vapier Exp $ +# $Header: /var/cvsroot/gentoo-x86/x11-drivers/xf86-video-ati/xf86-video-ati-6.5.7.3.ebuild,v 1.7 2006/03/21 22:53:10 lu_zero Exp $ # Must be before x-modular eclass is inherited #SNAPSHOT="yes" @@ -23,6 +23,7 @@ DEPEND="${RDEPEND} >=x11-libs/libdrm-2 )" CONFIGURE_OPTIONS="$(use_enable dri)" +PATCHES="${FILESDIR}/${P}-hangup-ppc.patch" pkg_setup() { if use dri && ! built_with_use x11-base/xorg-server dri; then |